#ifndef PROFILER_H
#define	PROFILER_H

#include <stdint.h>
#include "../6502.h"
#include "../List.h"
#include "BasicBlock.h"
#include "TU.h"
#include "CFG.h"

#ifdef	__cplusplus
extern "C" {
#endif

#define PROFILER_DEBUG 1 
//#define TRANSITION_DEBUG 1
    
typedef struct{
    const char* (*InstructionPtr)();
    __AddrModes AddressingMode;
    uint8_t Size;
    uint8_t OpCycles;
    uint8_t CTInstruction;              //Control-transfer instruction? 1 = Unconditional Jump, 2 = Conditional Branch
    uint8_t LastEffectiveAddressInstruction;
} InstructionProfilingData;    
    
typedef struct ProfData{
    TranslationUnit* CurrentBasicBlock;      //Points to the current Basic Block
    TranslationUnit* CurrentTU;
    __LinkedList* CFGs;                      //A list of all control-flow graphs touched in the current epoch
    ControlFlowGraph* CurrentCFG;            //Pointer to the Current CFG
    
    uint64_t Epoch;                      //Indicates which execution epoch we're in
    uint32_t EpochCounter;               //Indicates how many translation units should execute until the end of the current epoch
    
    uint8_t LastCF;                      //Indicates that the last instruction executed was a control-flow instruction
    
    uint32_t Interpreting;              //Indicates whether or not the current Translation Unit is being Interpreted (and profiled)
    
    //TODO: add some kind of mechanism to keep track of which basic blocks were split
    //TODO: create a data structure that keeps the traces forged in this epoch.
    // --> Maybe a list of pointers to the control flow graph?
    
} ProfData;

// Initializes Profiler data structure
void ProfilerInit(void);

// This is the routine that does the profiling on instruction interpretation.
// Based on the instruction initial address, the profiler is responsible for
// constructing a basic block if none is found for a particular instruction.
// Also, the profiler is in charge of constructing a control-flow graph for the
// program, as well as generating execution traces in an epoch-based approach.
void ProfileIntRoutine(uint16_t Address);

void ProfileTranslatedRoutine(uint16_t Address);

void SetNewCFG(void);

void NewEpoch(void);

void PROF_PrintCFGs(char* DotFilename);

#ifdef	__cplusplus
}
#endif

#endif	/* PROFILER_H */

